package com.hemerasolutions.v2trainer.component.table;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

import com.hemerasolutions.v2trainer.component.BaseComponent;
import com.hemerasolutions.v2trainer.component.interfaces.detail.ExerciseDetailsCompInterface;
import com.hemerasolutions.v2trainer.component.interfaces.list.IntensityZoneListCompInterface;
import com.hemerasolutions.v2trainer.component.interfaces.table.ExerciseTableCompInterface;
import com.hemerasolutions.v2trainer.delegate.interfaces.ExerciseDetailDelegateInterface;
import com.hemerasolutions.v2trainer.delegate.interfaces.ExerciseTableDelegateInterface;
import com.hemerasolutions.v2trainer.model.exercise.Exercise;
import com.hemerasolutions.v2trainer.model.exercise.VersionableExercise;
import com.hemerasolutions.v2trainer.model.exercise.executions.Execution;
import com.hemerasolutions.v2trainer.model.modality.Modality;
import com.hemerasolutions.v2trainer.model.muscle.BodyRegion;
import com.hemerasolutions.v2trainer.model.muscle.Muscle;
import com.hemerasolutions.v2trainer.model.muscle.MuscleGroup;
import com.hemerasolutions.v2trainer.model.training.Training;
import com.hemerasolutions.v2trainer.service.interfaces.ModalityServiceInterface;


@Controller
@Component("exerciseTableComp")
@Scope("prototype")
public class ExerciseTableComp extends BaseComponent implements ExerciseTableCompInterface, ExerciseDetailDelegateInterface {

	private static final long serialVersionUID = 1L;
	
	private Modality modality;
	
	private Exercise exercise;
	
	private ExerciseTableDelegateInterface delegate;
	
	private VersionableExercise versionableExercise;
	
	private List<VersionableExercise> filteredExercises;
	
	private String filterExerciseByName;

	private String filterExerciseByDescription;

	private List<Execution> filterExerciseByExecutions;

	private Boolean filterExerciseByTechnical;

	private Boolean filterExerciseByDefault;

	private List<Execution> fullExecutions;

	private List<BodyRegion> fullBodyRegions;

	private ArrayList<MuscleGroup> fullMuscleGroups;

	private ArrayList<Muscle> fullMuscles;		
	
	private List<BodyRegion> filterExerciseByBodyRegions;

	private List<MuscleGroup> filterExerciseByMuscleGroups;

	private List<Muscle> filterExerciseByMuscles;	

	@Autowired
	private ModalityServiceInterface modalityService;
	
	@Autowired
	private IntensityZoneListCompInterface izList;
	
	@Autowired
	private ExerciseDetailsCompInterface exerciseDetailsComp;
	
	public ExerciseTableComp(){
		super();
	}
	
	@Override
	@PostConstruct
	public void init(){
		super.init();
		
		filterExerciseByExecutions = new ArrayList<Execution>() ;
		filterExerciseByBodyRegions = new ArrayList<BodyRegion>();
		filterExerciseByMuscleGroups = new ArrayList<MuscleGroup>();
		filterExerciseByMuscles = new ArrayList<Muscle>();			
	}
	
	
	@Override
	public void refresh(){

		if(this.modality != null){
			this.filteredExercises = new ArrayList<VersionableExercise>();
			this.filteredExercises.addAll(this.modality.getVersionableExercises());
		}
		
	}
	
	@Override
	public void toAddExercise(){
		this.versionableExercise = new VersionableExercise(this.modality);

		this.exerciseDetailsComp.setDelegate(this);
		this.exerciseDetailsComp.setModality(this.modality);
		this.exerciseDetailsComp.setVersionableExercise(this.versionableExercise);
		this.exerciseDetailsComp.setExercise(this.versionableExercise.getCurrentVersion());
		
		this.exerciseDetailsComp.refresh();
		
	}
	
	@Override
	public void toFilterExercises(){
		this.fullExecutions = this.modality.getExecutions();
		this.fullBodyRegions = this.modalityService.listBodyRegion();
		this.fullMuscleGroups = new ArrayList<MuscleGroup>();
		this.fullMuscles = new ArrayList<Muscle>();		
	}


	@Override
	public void toViewExercise(){
		this.exercise = this.versionableExercise.getExercise();

		this.exerciseDetailsComp.setModality(this.modality);
		this.exerciseDetailsComp.setVersionableExercise(this.versionableExercise);
		this.exerciseDetailsComp.setExercise(this.exercise);
		this.exerciseDetailsComp.setDelegate(this);
		this.exerciseDetailsComp.refresh();
	}

	
	@Override
	public void filterExercises(){
		this.filteredExercises = new ArrayList<VersionableExercise>();
		
		for(VersionableExercise ve:this.modality.getVersionableExercises()){
			for(Exercise exec:ve.getExerciseVersions()){
	
		    	if (this.filterExerciseByName != null && !exec.getName().toUpperCase().contains(this.filterExerciseByName.toUpperCase())){
		    		continue;
		    	}
	
		    	if (this.filterExerciseByDescription != null && !exec.getDescription().toUpperCase().contains(this.filterExerciseByDescription.toUpperCase())){
		    		continue;
		        }
	
		    	
		    	if( this.filterExerciseByExecutions != null && !this.filterExerciseByExecutions.isEmpty()){
		    		if(!this.hasAnyOfList(this.filterExerciseByExecutions,exec.getExecutions())){
		    			continue;
		    		}
		    	}
	
		    	if( this.filterExerciseByBodyRegions != null && !this.filterExerciseByBodyRegions.isEmpty()){
		    		if(!this.hasAnyOfList(this.filterExerciseByBodyRegions,exec.getBodyRegions())){
		    			continue;
		    		}
		    	}
	
		    	if( this.filterExerciseByMuscleGroups != null && !this.filterExerciseByMuscleGroups.isEmpty()){
		    		if(!this.hasAnyOfList(this.filterExerciseByMuscleGroups,exec.getMuscleGroups())){
		    			continue;
		    		}
		    	}
	
		    	if( this.filterExerciseByMuscles != null && !this.filterExerciseByMuscles.isEmpty()){
		    		if(!this.hasAnyOfList(this.filterExerciseByMuscles,exec.getAllMuscles())){
		    			continue;
		    		}
		    	}
		    	
		    	if(this.filterExerciseByTechnical != null &&!exec.isTechnical() == this.filterExerciseByTechnical){
		    		continue;
		    	}
	
		    	if( this.filterExerciseByDefault != null && !exec.isDefaultExercise() == this.filterExerciseByDefault){
		    		continue;
		    	}
	
		    	
		    	if(!this.filteredExercises.contains(ve)){
					this.filteredExercises.add(ve);	
		    	}
			}
		}


		this.filteredExercises = this.delegate.onFilterExercises(this.filteredExercises);
		
		if((this.filteredExercises).isEmpty()){
			this.showInfoMessage(	this.localizedText("SearchCompleted"),
									this.localizedText("NoEntrysFounded"));
		}else{
			this.showInfoMessage(	this.localizedText("SearchCompleted"),
									this.filteredExercises.size() + " " + 
									this.localizedText("entrysFounded"));
		}
		
		this.exercise = null;
		
	}

	private <T> boolean hasAnyOfList(List<T> listFull, List<T> listItens) {

		for(Object ob:listFull){
			if(listItens.contains(ob)){
				return true;
			}
		}
		
		return false;
	}

	@Override
	public void toAdjustIntensitys(){
		this.exercise = this.versionableExercise.getCurrentVersion();
		this.izList.setVersionabeExercise(this.versionableExercise);
		this.izList.setExercise(this.versionableExercise.getCurrentVersion());
		this.izList.setModality(this.modality);
		this.izList.refresh();
		
	}
	
	@Override
	public void deleteExercise(){
		List<Training> trainings = this.modalityService.trainingsUsingExercises(this.versionableExercise.getExerciseVersions());
		
		if( trainings != null && !trainings.isEmpty()){
			this.showErrorMessage(this.localizedText("Error"), this.localizedText("ErrorOnDelete"));
			this.showWhereExerciseIsUsed(trainings);
		}else{
			this.modality.getVersionableExercises().remove(this.versionableExercise);	
			this.filteredExercises.remove(this.versionableExercise);
			this.exercise = null;
			this.versionableExercise = null;
			this.izList.refresh();
		}
		
		
	}
	
	private void showWhereExerciseIsUsed(List<Training> trainings){

		for(Training training:trainings){
			if(!training.isTrainingSystem()){
				this.showErrorMessage(	this.localizedText("ErrorOnChange"),
										this.localizedText("TheExerciseIsUsedOnTraining") + " " +
										training.getName());
			}
		}
		
	}	
	
	@Override
	public void changeFullBodyRegions(){
		this.fullMuscleGroups = new ArrayList<MuscleGroup>();
		for(BodyRegion br:this.filterExerciseByBodyRegions){
			for(MuscleGroup mg:br.getMuscleGroups()){
				this.fullMuscleGroups.add(mg);
			}
		}
	}

	
	@Override
	public void changeFullMuscleGroups(){
		this.fullMuscles = new ArrayList<Muscle>();
		for(MuscleGroup mg:this.filterExerciseByMuscleGroups){
			for(Muscle musc:mg.getMuscles()){
				this.fullMuscles.add(musc);
			}
		}
	}

	@Override
	public Modality getModality() {
		return modality;
	}

	@Override
	public void setModality(Modality modality) {
		this.modality = modality;
	}

	@Override
	public Exercise getExercise() {
		return exercise;
	}

	@Override
	public void setExercise(Exercise exercise) {
		this.exercise = exercise;
	}

	@Override
	public List<VersionableExercise> getFilteredExercises() {
		return filteredExercises;
	}

	@Override
	public void setFilteredExercises(List<VersionableExercise> filteredExercises) {
		this.filteredExercises = filteredExercises;
	}

	@Override
	public String getFilterExerciseByName() {
		return filterExerciseByName;
	}

	@Override
	public void setFilterExerciseByName(String filterExerciseByName) {
		this.filterExerciseByName = filterExerciseByName;
	}

	@Override
	public String getFilterExerciseByDescription() {
		return filterExerciseByDescription;
	}

	@Override
	public void setFilterExerciseByDescription(String filterExerciseByDescription) {
		this.filterExerciseByDescription = filterExerciseByDescription;
	}

	@Override
	public List<Execution> getFilterExerciseByExecutions() {
		return filterExerciseByExecutions;
	}

	@Override
	public void setFilterExerciseByExecutions(
			List<Execution> filterExerciseByExecutions) {
		this.filterExerciseByExecutions = filterExerciseByExecutions;
	}

	@Override
	public Boolean getFilterExerciseByTechnical() {
		return filterExerciseByTechnical;
	}

	@Override
	public void setFilterExerciseByTechnical(Boolean filterExerciseByTechnical) {
		this.filterExerciseByTechnical = filterExerciseByTechnical;
	}

	@Override
	public Boolean getFilterExerciseByDefault() {
		return filterExerciseByDefault;
	}

	@Override
	public void setFilterExerciseByDefault(Boolean filterExerciseByDefault) {
		this.filterExerciseByDefault = filterExerciseByDefault;
	}

	@Override
	public List<Execution> getFullExecutions() {
		return fullExecutions;
	}

	@Override
	public void setFullExecutions(List<Execution> fullExecutions) {
		this.fullExecutions = fullExecutions;
	}

	@Override
	public List<BodyRegion> getFullBodyRegions() {
		return fullBodyRegions;
	}

	@Override
	public void setFullBodyRegions(List<BodyRegion> fullBodyRegions) {
		this.fullBodyRegions = fullBodyRegions;
	}

	@Override
	public ArrayList<MuscleGroup> getFullMuscleGroups() {
		return fullMuscleGroups;
	}

	@Override
	public void setFullMuscleGroups(ArrayList<MuscleGroup> fullMuscleGroups) {
		this.fullMuscleGroups = fullMuscleGroups;
	}

	@Override
	public ArrayList<Muscle> getFullMuscles() {
		return fullMuscles;
	}

	@Override
	public void setFullMuscles(ArrayList<Muscle> fullMuscles) {
		this.fullMuscles = fullMuscles;
	}

	@Override
	public List<BodyRegion> getFilterExerciseByBodyRegions() {
		return filterExerciseByBodyRegions;
	}

	@Override
	public void setFilterExerciseByBodyRegions(
			List<BodyRegion> filterExerciseByBodyRegions) {
		this.filterExerciseByBodyRegions = filterExerciseByBodyRegions;
	}

	@Override
	public List<MuscleGroup> getFilterExerciseByMuscleGroups() {
		return filterExerciseByMuscleGroups;
	}

	@Override
	public void setFilterExerciseByMuscleGroups(
			List<MuscleGroup> filterExerciseByMuscleGroups) {
		this.filterExerciseByMuscleGroups = filterExerciseByMuscleGroups;
	}

	@Override
	public List<Muscle> getFilterExerciseByMuscles() {
		return filterExerciseByMuscles;
	}

	@Override
	public void setFilterExerciseByMuscles(List<Muscle> filterExerciseByMuscles) {
		this.filterExerciseByMuscles = filterExerciseByMuscles;
	}

	@Override
	public IntensityZoneListCompInterface getIzList() {
		return izList;
	}

	@Override
	public void setIzList(IntensityZoneListCompInterface izList) {
		this.izList = izList;
	}

	@Override
	public ExerciseDetailsCompInterface getExerciseDetailsComp() {
		return exerciseDetailsComp;
	}

	@Override
	public void setExerciseDetailsComp(
			ExerciseDetailsCompInterface exerciseDetailsComp) {
		this.exerciseDetailsComp = exerciseDetailsComp;
	}

	public VersionableExercise getVersionableExercise() {
		return versionableExercise;
	}

	public void setVersionableExercise(VersionableExercise versionableExercise) {
		this.versionableExercise = versionableExercise;
	}

	@Override
	public void onSaveVersionableExercise( VersionableExercise versionableExercise) {
		this.refresh();
	}

	@Override
	public void selectVersionableExercise(){
		this.delegate.onVersionableExerciseSelected(this.versionableExercise);
	}
	
	@Override
	public ExerciseTableDelegateInterface getDelegate() {
		return delegate;
	}

	@Override
	public void setDelegate(ExerciseTableDelegateInterface delegate) {
		this.delegate = delegate;
	}

	
}
